package cn.edu.hit.mongodb;

import cn.edu.hit.core.Document;
import cn.edu.hit.core.db.DataConnection;
import cn.edu.hit.core.db.DataReader;
import cn.edu.hit.kg.Neo4jConfigurationUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.*;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.BsonDocument;
import org.bson.BsonDocumentWrapper;
import org.bson.codecs.BsonTypeClassMap;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.conversions.Bson;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class MongoDBConnection implements DataConnection {
    private static ObjectMapper mapper = new ObjectMapper();
    private static final String defaultUrl = "mongodb://localhost:27017";
    private MongoClient mongoClient;

    private static CodecRegistry registry;
    private static MapLikedDocumentCodec<Map<String, Object>> documentCodec;
    private MongoCollection<Document> collection;

    static {
        CodecRegistry rawRegistry = MongoClient.getDefaultCodecRegistry();
        documentCodec = new MapLikedDocumentCodec(rawRegistry, new BsonTypeClassMap(), Map.class, Document::new);
        CodecRegistry newRegistry = CodecRegistries.fromCodecs(documentCodec);
        registry = CodecRegistries.fromRegistries(newRegistry, rawRegistry);
    }

    @Override
    public boolean connect(Map connectParams) {
        String url = (String) connectParams.getOrDefault("mongoUrl", defaultUrl);
        String databaseName = (String) connectParams.getOrDefault("database_name", "fault");
        String schema = (String) connectParams.getOrDefault("schema", "configure");
        MongoClientURI connectionString = new MongoClientURI(url);

        try {
            mongoClient = new MongoClient(connectionString);
            MongoDatabase database = loadDatabase(databaseName);
            collection = database.getCollection(schema, Document.class);
        } catch (Exception ex) {
            return false;
        }

        return true;
    }

    public MongoDatabase loadDatabase(String database) {
        return mongoClient.getDatabase(database).withCodecRegistry(registry);
    }

    @Override
    public DataReader getReader() {
        return new MongoDB(collection);
    }

    public static BsonDocument toBson(Map<String, Object> document) {
        return new BsonDocumentWrapper<>(document, documentCodec);
    }

    public static List<Bson> asList(Document... documents) {
        return Arrays.stream(documents).map(MongoDBConnection::toBson).collect(Collectors.toList());
    }

    public static String toJson(Document document) {
        try {
            return mapper.writeValueAsString(document);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Document parse(String json) {
        try {
            return mapper.readValue(json, Document.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
//        MongoCredential credential = MongoCredential.createCredential("admin", "test2", "123456".toCharArray());
//        MongoClient mongoClient = new MongoClient(new ServerAddress("localhost", 27017), Arrays.asList(credential));
//        System.out.println("Connect to database successfully");
//        DB database = mongoClient.getDB("test2");//获取数据库
//        System.out.println("11112");
//        MongoCollection<Document> collection = database.getCollection("test");//集合名
//        System.out.println("11sd2");
//       // BasicDBObject docss = new BasicDBObject();
//      //  long a = collection.count();
//        System.out.println("1");


//        MongoClient mongoClient = new MongoClient();
//
//        MongoDatabase mongoDatabase = mongoClient.getDatabase("test");
//        MongoCollection<org.bson.Document> collection = mongoDatabase.getCollection("user");
//
//        Document document = new Document("name","张三")
//                .append("sex", "男")
//                .append("age", 18);
//
//        collection.insertOne(document);
    }
}
